package com.sky.service.admin.impl;

import com.sky.dto.GoodsSalesDTO;
import com.sky.exception.ParameterIsNullException;
import com.sky.mapper.admin.AdminOrderMapper;
import com.sky.pojo.OrderDayAmountVo;


import com.sky.result.Result;
import com.sky.service.admin.ReportService;
import com.sky.vo.*;
import lombok.extern.slf4j.Slf4j;


import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;


import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ReportServiceImpl implements ReportService {

    @Autowired
    private AdminOrderMapper adminOrderMapper;

    /**
     * 根据时间区间统计营业额
     * @param begin
     * @param end
     * @return
     */
    @Override
    public Result<TurnoverReportVO> turnoverStatistics(LocalDate begin, LocalDate end) {

        end=end.plusDays(1);
        //参数判空
        if(begin==null || end==null){
            throw new ParameterIsNullException("参数异常");
        }
        //指定时间段之内的每一天的销售额
        /**
         *  2种做法：(一条sql)
         *    第一种做法：简单， 循环，一天一天的查询
         *    第二种做法：复杂，一条sql语句查询出来
         */
        List<String> dataList = new ArrayList<>();
        List<Double> turnoverList = new ArrayList<>();
        while (begin.isBefore(end)){
            dataList.add(begin.toString());
            //都要查询当天的数据
            Double salesVolume =  adminOrderMapper.selectSalesVolumesByDay(begin.toString());

            if(salesVolume==null){
                salesVolume=0.0; //当天查询到数据，重置为0
            }
            turnoverList.add(salesVolume);

            //begin往后数一天
            begin = begin.plusDays(1);
        }

        //封装给前端
        String dateListStr = org.apache.commons.lang3.StringUtils.join(dataList, ",");
        String turnoverListStr = org.apache.commons.lang3.StringUtils.join(turnoverList, ",");
        TurnoverReportVO turnoverReportVO = new TurnoverReportVO();
        turnoverReportVO.setTurnoverList(turnoverListStr);
        turnoverReportVO.setDateList(dateListStr);
        return Result.success(turnoverReportVO);
    }

   /* @Override
    public OrderReportVO orderStatistics(LocalDate begin, LocalDate end) {
        List<LocalDate> allDays = getAllDays(begin,end);
        List<Integer> totalList = new ArrayList<>();
        List<Integer> completeList = new ArrayList<>();

        List<OrderReportVO> orderReportVOS = adminOrderMapper.ordersStatistics(begin,end.plusDays(1));
        for (LocalDate oneDay : allDays) {
            OrderReportVO orderReportVO = orderReportVOS.stream().filter(o ->o.getOrderCountList().equals(oneDay)).findFirst().orElse(null);
            if (orderReportVO == null){
                totalList.add(0);
                completeList.add(0);
            }else {
                totalList.add(orderReportVO.getTotalOrderCount());
                completeList.add(orderReportVO.getValidOrderCount());
            }
        }
        Integer totalNum = totalList.stream().reduce(Integer::sum).get();
        Integer complete = completeList.stream().reduce(Integer::sum).get();
        double rate = 0d;
        if (totalNum != 0){
            rate = (double) complete/totalNum;
        }
        OrderReportVO reportVO = OrderReportVO.builder().dateList(org.springframework.util.StringUtils.collectionToCommaDelimitedString(allDays))
                .validOrderCountList( org.springframework.util.StringUtils.collectionToCommaDelimitedString(completeList))
                .orderCountList(org.springframework.util.StringUtils.collectionToCommaDelimitedString(totalList))
                .totalOrderCount(totalNum)
                .validOrderCount(complete)
                .orderCompletionRate(rate)
                .build();
        return reportVO;
    }*/
   @Override
   public Result<OrderReportVO> orderStatistics(LocalDate begin, LocalDate end) {
       List<LocalDate> allDays = getAllDays(begin, end);
       List<Integer> totalList = new ArrayList<>();
       List<Integer> completeList = new ArrayList<>();
       List<OrderDayAmountVo> orderDayAmountVos = adminOrderMapper.orderStatistics(begin, end.plusDays(1));
       for (LocalDate oneDay : allDays) {
           OrderDayAmountVo orderDayAmountVo = orderDayAmountVos.stream().filter(o -> o.getOrderTime().equals(oneDay)).findFirst().orElse(null);
           if (orderDayAmountVo==null){
               totalList.add(0);
               completeList.add(0);
           }else {
               totalList.add(orderDayAmountVo.getTotalNum());
               completeList.add(orderDayAmountVo.getCompleteNum());
           }
       }
       Integer totalNum = totalList.stream().reduce(Integer::sum).get();
       Integer complete = completeList.stream().reduce(Integer::sum).get();
       double rate =0d;
       if (totalNum!=0){
           rate =(double) complete/totalNum;
       }
       OrderReportVO reportVO = OrderReportVO.builder().dateList(StringUtils.collectionToCommaDelimitedString(allDays))
               .validOrderCountList(StringUtils.collectionToCommaDelimitedString(completeList))
               .orderCountList(StringUtils.collectionToCommaDelimitedString(totalList))
               .totalOrderCount(totalNum)
               .validOrderCount(complete)
               .orderCompletionRate(rate)
               .build();
       return Result.success(reportVO);
   }

    @Override
    public SalesTop10ReportVO top10(LocalDate begin, LocalDate end) {
        List<GoodsSalesDTO> salesDTOS = adminOrderMapper.dishTop10(begin,end.plusDays(1));
        List<String> nameList = salesDTOS.stream().map(GoodsSalesDTO::getName).collect(Collectors.toList());
        List<Integer> numList = salesDTOS.stream().map(GoodsSalesDTO::getNumber).collect(Collectors.toList());
        SalesTop10ReportVO reportVO = SalesTop10ReportVO.builder()
                .nameList(StringUtils.collectionToCommaDelimitedString(nameList))
                .numberList(StringUtils.collectionToCommaDelimitedString(numList))
                .build();


        return reportVO;
    }

    @Override
    public UserReportVO userStatistics(LocalDate begin, LocalDate end) {
        String oldBegin = begin.toString();
        String oldEnd = end.toString();
        //获取日期的集合
        List<String> dateList = new ArrayList<>();
        //用户总量集合
        List<Integer> totalUserList = new ArrayList<>();
        //新增用户集合
        List<Integer> newUserList = new ArrayList<>();
        end = end.plusDays(1);
        while (begin.isBefore(end)){
            dateList.add(begin.toString());
            begin=begin.plusDays(1);
        }

        //1.查询起始时间之前的所有用户数量
        int total = adminOrderMapper.selectUserTotalByDate(oldBegin);

        //2.根据时间段查询每日的用户新增数量
        Map<String,Object> res =  adminOrderMapper.selectEveryDayNewUserTotalByDate(oldBegin,oldEnd,dateList);

        //3.组装数据返回即可
        for(String date:dateList) {
            //获取每一天的新增数
            int newUsers = Integer.parseInt(res.get(date).toString());
            newUserList.add(newUsers);
            //累计为当日的用户总数
            total += newUsers;
            totalUserList.add(total);
        };


        UserReportVO userReportVO = UserReportVO.builder()
                .dateList(org.apache.commons.lang3.StringUtils.join(dateList,","))
                .newUserList(org.apache.commons.lang3.StringUtils.join(newUserList,","))
                .totalUserList(org.apache.commons.lang3.StringUtils.join(totalUserList,","))
                .build();

        return userReportVO;



    }

    /**
     * 生成数据报表
     * @param response
     * @throws IOException
     */
    @Override
    public void exportBusinessData(HttpServletResponse response) throws IOException {
        //获取当前时间和开始时间
        LocalDate now = LocalDate.now();
        LocalDate begin = now.minusDays(30);
        //读取准备的excel文件，读取格式
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("templates/运营数据报表.xlsx");
        //POI组件初始化 把读取到的文件输入进来，
        XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
        XSSFSheet sheet = workbook.getSheetAt(0);
        //先设置时间
        XSSFRow row = sheet.getRow(1);
        row.getCell(1).setCellValue("时间："+begin +"至"+now);
        //写概览数据（上面几行）
        OrderDayAmountVo orderDayAmountVo = adminOrderMapper.orderExportBaseData(begin,now);
        BusinessDataVO dataVO = buildBusinessData(orderDayAmountVo, now);

        XSSFRow row4 = sheet.getRow(3);
        row4.getCell(2).setCellValue(dataVO.getTurnover());
        row4.getCell(4).setCellValue(dataVO.getOrderCompletionRate());
        row4.getCell(6).setCellValue(dataVO.getNewUsers());

        XSSFRow row5 = sheet.getRow(4);
        row5.getCell(2).setCellValue(dataVO.getValidOrderCount());
        row5.getCell(4).setCellValue(dataVO.getUnitPrice());

        int beginIndex = 7;
        //获取每天的订单数据
        List<OrderDayAmountVo> orderDayAmountVos = adminOrderMapper.orderStatistics( begin, now);

        while(!begin.equals(now)){
            LocalDate tempDate = begin;
            OrderDayAmountVo dayAmountVo = orderDayAmountVos.stream().filter(o -> o.getOrderTime().equals(tempDate)).findFirst().orElse(null);
            dataVO = buildBusinessData(dayAmountVo, begin);
            XSSFRow dataRow = sheet.getRow(beginIndex);
            dataRow.getCell(1).setCellValue(begin.toString());
            dataRow.getCell(2).setCellValue(dataVO.getTurnover());
            dataRow.getCell(3).setCellValue(dataVO.getValidOrderCount());
            dataRow.getCell(4).setCellValue(dataVO.getOrderCompletionRate());
            dataRow.getCell(5).setCellValue(dataVO.getUnitPrice());
            dataRow.getCell(6).setCellValue(dataVO.getNewUsers());

            beginIndex++;
            begin = begin.plusDays(1);
        }

        workbook.write(response.getOutputStream());
        workbook.close();

    }
    private BusinessDataVO buildBusinessData(OrderDayAmountVo amountVo,LocalDate date){
        //封装新增用户数
        Integer newUser = adminOrderMapper.getNewUser(date);
        if(amountVo == null){
            return new BusinessDataVO(0d,0,0d,0d,newUser);
        }
        int completeNum = amountVo.getCompleteNum();
        int totalNum = amountVo.getTotalNum();
        double price = 0;
        if(completeNum != 0) {
            price = amountVo.getAmount().doubleValue() / completeNum;
        }

        BusinessDataVO businessDataVO = BusinessDataVO.builder().validOrderCount(completeNum)
                .turnover(amountVo.getAmount().doubleValue())
                .orderCompletionRate((double) completeNum / totalNum)
                .unitPrice(price)
                .newUsers(newUser).build();

        return businessDataVO;
    }


   //创建 从开始到结束的日期列表，用于和数据配对
    private List<LocalDate> getAllDays(LocalDate begin, LocalDate end){
        ArrayList<LocalDate> allDays = new ArrayList<>();
        allDays.add(begin);
        while(!begin.equals(end)){
            begin = begin.plusDays(1);
            allDays.add((begin));
        }
        return allDays;
    }


}